using AutoMapper;
using Microsoft.Extensions.Logging;
using ORS.OrderRobot.Domain;
using ORS.OrderRobot.IOC;
using ORS.OrderRobot.Service.Jobs;
using ORS.OrderRobot.ServiceContracts;
using ORS.OrderRobot.ServiceContracts.Dtos;

namespace ORS.OrderRobot.Service;
/// <summary>
/// 账号服务
/// </summary>
public class AccountService : IAccountService, IScoped
{
    private readonly IRepository<Account,int> _accountRepository;
    private readonly IAccountBoardingRepository _accountBoardingRepository;
    private readonly IRepository<AccountOrder, int> _accountOrderRepository;
    private readonly IMapper _mapper;
    private readonly ILogger<AccountService> _logger;
    private readonly IBackgroundJobManager _backgroundJobManager;
    private readonly IFlightInfoService _flightInfoService;
    private readonly AccountCacheManager _accountCacheManager;
    public AccountService(
        IRepository<Account,int> accountRepository,
        IAccountBoardingRepository accountBoardingRepository,
        IRepository<AccountOrder, int> accountOrderRepository,
        IMapper mapper,
        ILogger<AccountService> logger,
        IBackgroundJobManager backgroundJobManager,
        IFlightInfoService flightInfoService,
        AccountCacheManager accountCacheManager)
    {
        _accountRepository = accountRepository;
        _accountBoardingRepository = accountBoardingRepository;
        _accountOrderRepository = accountOrderRepository;
        _mapper = mapper;
        _logger = logger;
        _backgroundJobManager = backgroundJobManager;
        _flightInfoService = flightInfoService;
        _accountCacheManager = accountCacheManager;
    }
    /// <summary>
    /// 验证输入参数
    /// </summary>
    private void ValidateInput(AccountInput input)
    {
        if (input.BoardingInfo != null)
        {
            var flightValid = FlightNoParser.Validate(input.BoardingInfo.FlightNo);
            if (!flightValid.validResult)
            {
                throw new Exception(flightValid.errMsg);
            }
            var depatureDate = DateOnly.Parse(input.BoardingInfo.DepartureDate.Replace("/", "-"));
            if (depatureDate <= DateOnly.FromDateTime(DateTime.Now.China()))
            {
                throw new Exception("出发日期必须大于今天");
            }
        }
    }

    /// <summary>
    /// 创建或更新账号
    /// </summary>
    private async Task<Account> CreateOrUpdateAccount(AccountBasicInput basicInfo)
    {
        var entity = await _accountRepository.GetAsync(x => x.Email == basicInfo.Email);
        if (entity == null)
        {
            // 账号不存在，创建新账号
            entity = new Account
            {
                Email = basicInfo.Email,
                Password = basicInfo.Password,
                IsActive = true,
                CreateTime = DateTime.Now.China(),
            };
            await _accountRepository.InsertAsync(entity);
        }
        else
        {
            // 账号存在，更新信息
            entity.IsActive = true;
            entity.Password = basicInfo.Password;
            await _accountRepository.UpdateAsync(entity);
        }
        await UpdateAccountsCache(basicInfo.Email, basicInfo.Password);
        return entity;
    }

    /// <summary>
    /// 处理登机牌信息
    /// </summary>
    private async Task<AccountBoarding> ProcessBoardingInfo(AccountBoardingInput boardingInfo, Account account)
    {
        // 创建登机牌实体
        var airlineInfo = FlightNoParser.Parse(boardingInfo.FlightNo);
        var flightData = await _flightInfoService.GetFlightInfo(airlineInfo.airlineCode, airlineInfo.flightNo);
        if (flightData == null)
        {
            throw new Exception("系统中找不到该航班信息");
        }
        var (firstName, lastName) = NameParser.Parse(boardingInfo.CustomName);
        var depatureDate = DateOnly.Parse(boardingInfo.DepartureDate.Replace("/", "-"));
        var depatureTime = TimeSpan.Parse(boardingInfo.DepartureTime);
        var boardingEntity = new AccountBoarding
        {
            AccountId = account.Id,
            Birthday = boardingInfo.Birthday,
            Phone_Mobile = boardingInfo.Mobile,
            DepartureDate = depatureDate,
            DepartureTime = depatureTime,
            Airlines = flightData.AirlineName,
            AirlinesNo = airlineInfo.airlineCode,
            FlightNo = airlineInfo.flightNo,
            PickupStoreCode = flightData.PickupStoreCode,
            First_Name = firstName,
            Last_Name = lastName,
            CreateTime = DateTime.Now.China(),
        };
        // 获取该账号所有登机牌，按Id排序，取最后一条
        var boardings = await _accountBoardingRepository.GetListAsync(x => x.AccountId == account.Id);
        var lastBoarding = boardings.OrderByDescending(x => x.Id).FirstOrDefault();
        // 账号没有创建过登机牌，直接插入
        if (lastBoarding == null)
        {
            await _accountBoardingRepository.InsertAsync(boardingEntity);
            await UpdateBoardingCache(boardingEntity, account);
        }
        else
        {
            // 判断该登机牌是否有关联订单
            var hasOrder = await _accountOrderRepository.ExistsAsync(x => x.BoardingId == lastBoarding.Id);
            // 有订单，新插入一条
            if (hasOrder)
            {
                await _accountBoardingRepository.InsertAsync(boardingEntity);
                await UpdateBoardingCache(boardingEntity, account);
            }
            else
            {
                lastBoarding.Birthday = boardingEntity.Birthday;
                lastBoarding.Phone_Mobile = boardingEntity.Phone_Mobile;
                lastBoarding.DepartureDate = boardingEntity.DepartureDate;
                lastBoarding.DepartureTime = boardingEntity.DepartureTime;
                lastBoarding.First_Name = boardingEntity.First_Name;
                lastBoarding.Last_Name = boardingEntity.Last_Name;
                lastBoarding.Airlines = boardingEntity.Airlines;
                lastBoarding.PickupStoreCode = boardingEntity.PickupStoreCode;
                lastBoarding.AirlinesNo = boardingEntity.AirlinesNo;
                lastBoarding.FlightNo = boardingEntity.FlightNo;
                lastBoarding.IsSyncToServer = false;
                lastBoarding.SyncTime = null;
                await _accountBoardingRepository.UpdateAsync(lastBoarding);
                boardingEntity.Id = lastBoarding.Id;
                await UpdateBoardingCache(boardingEntity, account);
            }
        }
        
        return boardingEntity;
    }

    /// <summary>
    /// 同步到第三方系统
    /// </summary>
    private async Task SyncToThirdParty(AccountInput input, AccountBoarding boardingEntity)
    {
        await _backgroundJobManager.EnqueueAsync<UpdateAccountProfileJob, UpdateProfileArgs>(new UpdateProfileArgs
        {
            BoardingId = boardingEntity.Id,
            Email = input.BaiscInfo.Email,
            Password = input.BaiscInfo.Password,
            Birthday = boardingEntity.Birthday,
            Phone_Mobile = boardingEntity.Phone_Mobile,
            First_Name = boardingEntity.First_Name,
            Last_Name = boardingEntity.Last_Name,
        });
    }
    /// <summary>
    /// 获取有效的登机信息，每个用户最多一条（有多条时，优先取id最大的）
    /// </summary>
    /// <returns></returns>
    private async Task<List<AccountBoardingDto>> GetAllActiveBoard(bool foreLoadFromDb = false)
    {
        var caches = await _accountCacheManager.GetAllBoarding();
        if ((caches == null || !caches.Any()) || foreLoadFromDb)
        {
            var nowTime = DateTime.Now.China();
            var boardings = await _accountBoardingRepository.GetListAsync(
                x => x.DepartureDate > DateOnly.FromDateTime(nowTime) && x.Account.IsActive == true,
                includeDetails: true
            );
            caches = _mapper.Map<List<AccountBoardingDto>>(boardings);
        }
        // 只保留每个AccountId id最大的那条
        var latestBoardings = caches
            .GroupBy(b => b.AccountId)
            .Select(g => g.OrderByDescending(b => b.Id).First())
            .ToList();
        await _accountCacheManager.SetAllBoarding(latestBoardings);
        return latestBoardings;
    }
    private async Task UpdateBoardingCache(AccountBoarding boardingEntity, Account entity)
    {
        var boardingCaches = await GetAllActiveBoard();
        // 移除所有同AccountId的旧数据，彻底去重
        boardingCaches.RemoveAll(x => x.AccountId == entity.Id);
        var cacheItem = _mapper.Map<AccountBoardingDto>(boardingEntity);
        cacheItem.AccountId = entity.Id;
        cacheItem.Email = entity.Email;
        boardingCaches.Add(cacheItem);
        await _accountCacheManager.SetAllBoarding(boardingCaches);
    }
    private async Task UpdateAccountsCache(string email, string password)
    {
        var allAccountCache = await _accountCacheManager.GetAccounts() ?? new Dictionary<string, string>();
        // 如果 email 已经存在，会更新 password；如果不存在，会添加新键值对
        allAccountCache[email] = password;
        await _accountCacheManager.SetAccounts(allAccountCache);
    }
    /// <summary>
    /// 添加或更新用户新和登机牌
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task CreateUpdateAsync(AccountInput input)
    {
        // 1. 验证输入
        ValidateInput(input);

        // 2. 处理账号（创建或更新）
        var account = await CreateOrUpdateAccount(input.BaiscInfo);

        // 3. 处理登机牌（如果有）
        AccountBoarding? boardingEntity = null;
        if (input.BoardingInfo != null)
        {
            boardingEntity = await ProcessBoardingInfo(input.BoardingInfo, account);
        }

        // 4. 同步到第三方（如果有登机牌）
        if (boardingEntity != null)
        {
            await SyncToThirdParty(input, boardingEntity);
        }
    }
    /// <summary>
    /// 获取系统中所有的账号
    /// </summary>
    /// <returns></returns>
    public async Task<List<AccountDto>> GetAllAsync(GetAllInput input)
    {
        var accounts = input.IsActive.HasValue
            ? await _accountRepository.GetListAsync(x => x.IsActive == input.IsActive.Value)
            : await _accountRepository.GetListAsync(x => true);
            if (!input.NeedBoarding)
            {
                // 直接批量映射
                return _mapper.Map<List<AccountDto>>(accounts);
            }
        var result = new List<AccountDto>();
        var accountIds = accounts.Select(a => a.Id).ToList();
        var nowTime = DateTime.Now.China();
        var allBoardingDtos = (await GetAllActiveBoard(input.LoadBoardingFromDb)).Where(i=>accountIds.Contains(i.AccountId));
        var tasks = new List<Task>();
        foreach (var account in accounts)
        {
            var accountDto = _mapper.Map<AccountDto>(account);
            var accountBoardingDto = allBoardingDtos.FirstOrDefault(x=>x.AccountId == account.Id);
            accountDto.CurrentBoarding = accountBoardingDto;
            result.Add(accountDto);
        }
        if (tasks.Count > 0)
        {
            await Task.WhenAll(tasks);
        }
        return result;
    }
    /// <summary>
    /// 获取基本账号信息
    /// </summary>
    /// <param name="email"></param>
    /// <returns></returns>
    public async Task<(string email, string password)?> GetAccount(string email)
    {
        string? password = null;
        var allAccountCache = await _accountCacheManager.GetAccounts();
        if(allAccountCache !=null && allAccountCache.Count > 0)
        {
            allAccountCache.TryGetValue(email, out password);
        }
        if(password == null)
        {
            var entity = await _accountRepository.GetAsync(x => x.Email == email && x.IsActive == true);
            password = entity?.Password;
        }
        if (password == null) return null;
        return (email, password);
    }
    public async Task SetActiveStatusAsync(AccountStatusInput input)
    {
        var entitys = await _accountRepository.GetListAsync(x => input.Emails.Any(e => x.Email == e));
        foreach (var entity in entitys)
        {
            entity.IsActive = input.IsActive;
            if (!input.IsActive)
            {
                await _accountCacheManager.RemoveLogin(entity.Email);
            }
            else
            {
                await UpdateAccountsCache(entity.Email, entity.Password); // 该方法已加锁
            }
        }
        await _accountRepository.UpdateManyAsync(entitys);
    }
    /// <summary>
    /// 获取用户有效的登机牌
    /// </summary>
    /// <param name="email"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    public async Task<AccountBoardingDto?> GetBoardingAsync(string email)
    {
        var boardings = await GetAllActiveBoard();
        return boardings.FirstOrDefault(x=>x.Email == email);
    }
    /// <summary>
    /// 同步用户资料到三方服务器
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    public async Task SyncProfileToThridPart(AccountBasicInput input)
    {
        var boardingDto = await GetBoardingAsync(input.Email);
        if(boardingDto == null)
        {
            throw new Exception("账号未设置姓名、电话等信息");
        }
        await _backgroundJobManager.EnqueueAsync<UpdateAccountProfileJob, UpdateProfileArgs>(new UpdateProfileArgs
        {
            BoardingId = boardingDto.Id,
            Email = input.Email,
            Password = input.Password,
            Birthday = boardingDto.Birthday,
            Phone_Mobile = boardingDto.Phone_Mobile,
            First_Name = boardingDto.First_Name,
            Last_Name = boardingDto.Last_Name,
        });
    }
}